﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

using System.IO;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Text;
using System.Collections.Generic;
using System.Collections;
using System.Data.SqlClient;
using System.Threading;
using Microsoft.VisualBasic;
using System.Net;
using FluorineFx.Json;
using System.Collections.Specialized;



namespace lxwmvc
{
    public class pagebase:IDisposable
    {       
        private bool _exit = false;
        private string _viewname = "";


        //是这部分的问题吗？
        string defaultcontroller = ConfigurationManager.AppSettings["defaultcontroller"];
        string defaultaction = ConfigurationManager.AppSettings["defaultaction"];

        /// <summary>
        /// 线程安全
        /// </summary>
        readonly static object[] syn = new object[0] { };

        /// <summary>
        /// 同步方法
        /// </summary>
        public static object m_monitorObject = new object();
        static Mutex m_mutex = new Mutex();//全局阻塞

        /// <summary>
        /// 默认输出json对象
        /// </summary>
        object _JSON = null;
        /// <summary>
        /// 输出json对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T JSON<T>(){
            return (T)_JSON;
        }
        /// <summary>
        /// 输出到界面里面
        /// </summary>
        Dictionary<string, object> data = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        /// <summary>
        /// 插入page数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public object this[string key]
        {
            get
            {
                if (data.ContainsKey(key))
                    return data[key];
                return "";
            }
            set
            {
                data[key] = value;
            }
        }

        /// <summary>
        /// 退出程序，后续不要再进行操作。
        /// </summary>
        public void exit(string msg = "MMM:人工终止操作！")
        {
            _exit = true;
            throw new Exception(msg);
        }


        

        string strcontroller = string.Empty;
        string straction = string.Empty;

       
        /// <summary>
        /// 通过pagebase 获取数据对象
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="qianzhun"></param>
        /// <returns></returns>
        public supermodel model(string tablename = "", string qianzhun = "")
        {
            supermodel has = supermodel.create(tablename);
            var arrs = new List<NameValueCollection>();
            if (Post) arrs.Add(Request.Form);
            arrs.Add(Request.QueryString);

            foreach (NameValueCollection Params in arrs)
            {
                foreach (string s in Params.Keys)
                {
                    if (!string.IsNullOrEmpty(s))//&& !s.Equals(key, StringComparison.OrdinalIgnoreCase))
                    {
                        if (qianzhun == "")
                            has[s.ToLower()] = getonevalue(s);
                        else
                        {
                            if (s.ToLower().StartsWith(qianzhun.ToLower()))
                            {
                                string key = s.Substring(qianzhun.Length).ToLower();
                                if (key.StartsWith(".") || key.StartsWith("_") || key.StartsWith(">")) key = key.Substring(1);//如果是._> 直接去除
                                has[key] = getonevalue(s);
                            }
                        }
                    }
                }
            }

            //特殊处理一下checkbox 等于on的情况
            string keys = v_s("_lxw_column_checkbox_").ToLower();
            foreach (string s in keys.Split(','))
            {
                if (s.Length == 0) continue;
                if (has.ContainsKey(s))  //这里是写死了，如果允许，就是1，不允许就是0，只有两种状态，是否允许再数据库中配置一下？
                    has[s] = has[s].tostr() == "on" ? 1 : 0;
                else
                    has[s] = 0;
            }

            return has;
        }

        /// <summary>
        /// 可能再次使用
        /// </summary>
        Type currenttype = null;
        int _StatusCode = (int)HttpStatusCode.OK;
        /// <summary>
        /// 
        /// </summary>
        public int StatusCode
        {
            set { _StatusCode = value; }
            //这个其实一般不用，先开放也可以
            get { return _StatusCode; }
        }

        /// <summary>
        /// 判断p1=true 然后抛出异常
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        public void ifcheck(bool p1, string p2)
        {
            if (p1) throw new Exception(p2);
        } 

        /// <summary>
        /// 页面加载核心函数
        /// </summary>
        /// <param name="_context"></param>
        public void execute(HttpContext _context)
        {
            try
            {
                //Request.ContentEncoding = Encoding.UTF8;
                Request = _context.Request;
                Response = _context.Response;
                Session = _context.Session;
                Server = _context.Server;
                Context = _context;

                strcontroller = _context.Items["_controller_"].ToString();
                straction = _context.Items["_action_"].ToString();

                if (strcontroller == "_defaultcontroller_") strcontroller = defaultcontroller;
                if (straction == "_defaultaction_") straction = defaultaction;

                _viewname = straction;
                MethodInfo currentmethod = null;
                //这里可能会存在问题
                currenttype = Type.GetType("lxwmvc." + strcontroller + "controller,angularjs_lxwmvcdll");
                currentmethod = getmethod(currenttype, straction, ref straction);
                //得到真实的
                _viewname = straction;
                //真实的action名称
                if (currentmethod != null)
                {
                    straction = currentmethod.Name.ToLower();                    
                }

                //List<Attribute> controllerattribute = new List<Attribute>();
                List<Attribute> actionattribute = new List<Attribute>();
                if (currentmethod != null)
                {
                    object[] attrs = currentmethod.GetCustomAttributes(false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        foreach (var o in attrs)
                        {
                            actionattribute.Add(o as Attribute);
                        }
                    }
                }

                if (currenttype != null)
                {
                    object[] attrs = currenttype.GetCustomAttributes(false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        foreach (var o in attrs)
                        {
                            actionattribute.Add(o as Attribute);
                        }
                    }
                }

                //查找事务
                var trans = actionattribute.Find(o => o.GetType() == typeof(transAttribute));
                if (trans != null) sqlhelper.starttranscation(trans);

                //调用会出现错误
                var _init = getmethod(currenttype, "_init");
                //这句话非常重要
                if (_init != null)
                    FastInvokeUtility.GetMethodInvoker(_init).Invoke(null, new object[] { this }); 

                var json = actionattribute.Find(o => o.GetType() == typeof(jsonAttribute));
                Type jsontype = null;
                if (currentmethod != null)
                {
                    if (json != null)
                    {
                        jsontype = ((jsonAttribute)json).jsontype;
                        _JSON = jsontype.Assembly.CreateInstance(jsontype.FullName);
                    }

                    Response.StatusCode = _StatusCode;
                    var lc = actionattribute.FindAll(o => o.GetType() == typeof(tongbuAttribute));

                    //执行方法如果出现错误。
                    try
                    {
                        if (lc == null || lc.Count == 0)
                        {
                            //currentmethod.Invoke(null, new object[] { this });
                            FastInvokeUtility.GetMethodInvoker(currentmethod).Invoke(null, new object[] { this });
                        }
                        else
                        {
                            try
                            {
                                //加方法锁
                                m_mutex.WaitOne();
                                //currentmethod.Invoke(null, new object[] { this });
                                FastInvokeUtility.GetMethodInvoker(currentmethod).Invoke(null, new object[] { this });
                            }
                            catch (Exception err)
                            {
                                throw err;
                            }
                            finally
                            {
                                m_mutex.ReleaseMutex();
                            }
                        }
                    }
                    catch (Exception err)
                    {
                        if (_JSON != null && _JSON.GetType() == typeof(BaseJson))
                        {
                            var _json = JSON<BaseJson>();
                            {
                                _json.success = false;
                                if(err.InnerException != null && !string.IsNullOrEmpty(err.InnerException.Message))
                                    _json.msg = err.InnerException.Message;
                                else
                                    _json.msg = err.Message;
                            };
                        }
                        else//如果不是json模式，直接返回到顶层
                        {
                            //throw err;
                            StringBuilder sb = new StringBuilder();
                            writeerrorlog(sb, err);

                            write(sb.tostr().Replace("\n","<br/>"));
                        }
                    }
                }
                else
                {
                    Response.StatusCode = (int)HttpStatusCode.NotFound;
                }

                //输出json对象
                if (json != null)
                {
                    Response.ContentType = "application/json";

                    var jsonString = JavaScriptConvert.SerializeObject(_JSON);
                    string p = @"new Date\((\d+)\)";
                    MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertJsonDateToDateString);
                    Regex reg = new Regex(p);
                    jsonString = reg.Replace(jsonString, matchEvaluator);
                    Response.Write(
                        jsonString
                    );
                }
                else
                {
                    Attribute temp = actionattribute.Find((Attribute o) => o.GetType() == typeof(tempAttribute));
                    if (temp != null)
                    {
                        string template = (temp as tempAttribute).template;
                        string path;
                        if (template.EndsWith("/") || template.EndsWith("\\"))
                        {
                            path = Path.Combine(Server.MapPath("/"), template + this._viewname + ".htm");
                        }
                        else
                        {
                            path = Path.Combine(Server.MapPath("/"), template + ".htm");
                        }
                        if (!File.Exists(path))
                        {
                            throw new Exception(path + "不存在!");
                        }

                        DateTime modifytime = File.GetLastWriteTime(path);
                        string cachekey = path + modifytime;
                        object cachecontent = HttpRuntime.Cache.Get(cachekey);
                        string filecontent = "";
                        if (cachecontent != null)
                        {
                            filecontent = cachecontent.tostr("", false);
                        }
                        else
                        {
                            using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
                            {
                                filecontent = sr.ReadToEnd();
                            }
                            HttpRuntime.Cache.Insert(cachekey, filecontent);
                        }
                        foreach (string key in this.data.Keys)
                        {
                            filecontent = Strings.Replace(filecontent, "#{" + key + "}", this.data[key].tostr("", false), 1, -1, CompareMethod.Text);
                        }
                        this.write(filecontent, new object[0]);
                    }                 
                }
                //统一提交事务
                sqlhelper.transactioncommit();
            }
            //[System.Threading.ThreadAbortException] = {由于代码已经过优化或者本机框架位于调用堆栈之上，无法计算表达式的值。}
            catch (ThreadAbortException)
            {
                Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                Console.Write("ThreadAbortException");
            }
            catch (Exception err)
            {
                dataloger.fatal("pagebase.execute", err);
                sqlhelper.transactionrollback();
                //错误信息
                Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                //throw err;
            }
            finally
            {
                sqlhelper.dbconnectclose();                
            }
        }

        private void writeerrorlog(StringBuilder sb, Exception exception)
        {
            sb.Append("错误类型:" + exception.GetType().Name + "\r\n");
            sb.Append("错误信息:" + exception.Message + "\r\n");

            if (!string.IsNullOrEmpty(exception.StackTrace))
                sb.Append("StackTrace:\r\n" + exception.StackTrace + "\r\n");

            if (exception.InnerException != null)
            {
                sb.Append("InnerException:\r\n");
                writeerrorlog(sb, exception.InnerException);
            }
        }
        /// <summary>
        /// json日期转换
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        string ConvertJsonDateToDateString(Match m)
        {
            string result = string.Empty;
            DateTime dt = new DateTime(1970, 1, 1);
            dt = dt.AddMilliseconds(long.Parse(m.Groups[1].Value));
            dt = dt.ToLocalTime();
            result = dt.ToString("yyyy-MM-dd HH:mm:ss");
            return "\""+result+"\"";
        }

        /// <summary>
        /// 得到方法体,也可以通过别名找
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="truename"></param>
        /// <returns></returns>
        MethodInfo getmethod(Type type, string name, ref string truename)
        {
            MethodInfo[] ms = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
            foreach (MethodInfo m in ms)
            {
                string bieming = m.Name;
                {
                    object[] attrs = m.GetCustomAttributes(typeof(biemingAttribute), false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        bieming = (attrs[0] as biemingAttribute).bieming;
                    }
                }

                //忽略大小写
                if (bieming.Trim().Equals(name.Trim(), StringComparison.OrdinalIgnoreCase))
                {
                    //别名作为新的vm文件
                    //_viewname = bieming.Trim();
                    truename = bieming.Trim();
                    return m;
                }
            }

            return null;
        }

        MethodInfo getmethod(Type type, string name)
        {
            return getmethod(type, name, ref name);
        }

        /// <summary>
        /// 没有值，或者转换失败，都用-1代替，也可以自己设置
        /// </summary>
        /// <param name="key"></param>
        /// <param name="def"></param>
        /// <returns></returns>
        public int v_i(string key, int def = -1)
        {
            string value = getonevalue(key);
            try
            {
                if (value == null)
                {
                    return def;
                }

                return value.toint32(def);
            }
            catch
            {
                return def;
            }
        }

        /// <summary>
        /// 获取字符串信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string v_s(string key)
        {
            string value = getonevalue(key);
            //sqlvalidator.checkstring(value);
            if (value == null)
            {
                return "";
            }

            return value;
        }

        /// <summary>
        /// 获取安全的字符串
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string v_ss(string key)
        {
            string value = getonevalue(key);
            if (value == null)
            {
                return "";
            }

            return value.Replace("'", "''").Split(';')[0];
        }

        /// <summary>
        /// 获取decimal对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public decimal v_dec(string key)
        {
            string value = getonevalue(key);
            try
            {
                if (value == null)
                {
                    return 0m;
                }

                return Convert.ToDecimal(value);
            }
            catch
            {
                return 0m;
            }
        }

        /// <summary>
        /// 获取日期对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public DateTime v_date(string key)
        {
            string value = getonevalue(key);
            try
            {
                if (value == null)
                {
                    return new DateTime(1900, 1, 1);
                }

                return Convert.ToDateTime(value);
            }
            catch
            {
                return new DateTime(1900, 1, 1);
            }
        }

        /// <summary>
        /// 获取前台传递过来的数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string getonevalue(string key)
        {
            string v = "";
            if (Post)
            {
                if (key.ToLower() == "page") return "0";
                v = Request.Form[key];
                if (v == null)
                {
                    v = Request.QueryString[key]??"";
                }
            }
            else
            {
                v = Request.QueryString[key]??"";
            }

            return v;
        }


        /// <summary>
        /// 输出信息
        /// </summary>
        /// <param name="p"></param>
        /// <param name="arg"></param>
        public void write(string p, params object[] arg)
        {
            Response.ContentType = "text/html";
            if (arg != null && arg.Length > 0)
                p = string.Format(p, arg);
            Response.Write(p);
        }

        /// <summary>
        /// 判断是否为POST请求
        /// </summary>
        public bool Post
        {
            get
            {
                return Request.HttpMethod.ToUpper() == "POST";
            }
        }

        /// <summary>
        /// 获取页面传输过来的json对象
        /// </summary>
        public JavaScriptObject bodyjson()
        {
            StreamReader sb = new StreamReader(Request.InputStream, Encoding.UTF8);
            var content = sb.ReadToEnd();

            JavaScriptObject o2 = JavaScriptConvert.DeserializeObject(
                content
                ) as JavaScriptObject;

            return o2;
        }

        /// <summary>
        /// Request
        /// </summary>
        public HttpRequest Request { get; set; }
        /// <summary>
        /// Response
        /// </summary>
        public HttpResponse Response { get; set; }
        /// <summary>
        /// Session
        /// </summary>
        public System.Web.SessionState.HttpSessionState Session { get; set; }

        public HttpServerUtility Server { get; set; }

        public HttpContext Context { get; set; }

        ~pagebase()
        {
            GC.SuppressFinalize(this);
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }

    /// <summary>
    /// ExitException
    /// </summary>
    public class ExitException : Exception
    {
        /// <summary>
        /// ExitException
        /// </summary>
        public ExitException() : base() { }
    }
}